use super::cache::{
    get_peer_connection, peer_connection_exist, push_peer_connection, update_peer_connection,
    PeerConnection, PeerConnectionState,
};
use crate::{
    signaling::{
        ice::{dial_response, IceMessage},
        send_string,
    },
    transport::{
        ice::{
            create_ice_data_channel, get_local_description_string, new_ice_connection,
            set_remote_candidate_by_string,
        },
        remove_connection,
    },
};
use chrono::Utc;
use std::{
    sync::{Arc, Mutex},
    thread::sleep,
    time::Duration,
};

pub async fn create_accept_channel(
    remote_peer_id: &String,
    remote_ufrag: &String,
    remote_pwd: &String,
    remote_candidates: &Vec<String>,
    request_id: Option<u64>,
) -> anyhow::Result<Arc<Mutex<PeerConnection>>> {
    //判断是否为自己
    if crate::is_self(remote_peer_id)? {
        return Err(anyhow::anyhow!("不允许本节点自身操作!"));
    }
    //判断是否存在
    let exist = peer_connection_exist(remote_peer_id)?;
    if exist {
        let peer_connection = get_peer_connection(remote_peer_id)?;
        //如果是在拨号还没有成功，则放弃，accept优先级高
        if peer_connection
            .lock()
            .map_err(|err| anyhow::anyhow!("{}", err))?
            .state
            == PeerConnectionState::Setuped
        {
            //
            return Ok(peer_connection);
        }
        tracing::debug!("存在连接，但是还没有建立完成!");
    }
    //新建
    let peer_connection = _create_accept_channel(
        remote_peer_id,
        remote_ufrag,
        remote_pwd,
        remote_candidates,
        request_id,
    )
    .await?;

    Ok(peer_connection)
}

pub async fn prepare_follower_channel(
    remote_peer_id: &String,
) -> anyhow::Result<Arc<Mutex<PeerConnection>>> {
    //判断是否为自己
    if crate::is_self(remote_peer_id)? {
        return Err(anyhow::anyhow!("不允许本节点自身操作!"));
    }
    //判断是否存在
    let exist = peer_connection_exist(remote_peer_id)?;
    if exist {
        return Ok(get_peer_connection(remote_peer_id)?);
    }

    Ok(_prepare_follower_channel(remote_peer_id).await?)
}

pub async fn create_follower_channel(
    remote_peer_id: &String,
    remote_ufrag: &String,
    remote_pwd: &String,
    remote_candidates: &Vec<String>,
    request_id: Option<u64>,
) -> anyhow::Result<Arc<Mutex<PeerConnection>>> {
    //判断是否为自己
    if crate::is_self(remote_peer_id)? {
        return Err(anyhow::anyhow!("不允许本节点自身操作!"));
    }
    //判断是否存在
    let peer_connection = get_peer_connection(remote_peer_id)?;

    if peer_connection
        .lock()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .state
        != PeerConnectionState::Dailed
    {
        //
        return Err(anyhow::anyhow!("需要提前准备!"));
    }
    //新建
    let peer_connection =
        _create_follower_channel(remote_peer_id, remote_ufrag, remote_pwd, remote_candidates)
            .await?;

    Ok(peer_connection)
}

async fn _create_accept_channel(
    remote_peer_id: &String,
    remote_ufrag: &String,
    remote_pwd: &String,
    remote_candidates: &Vec<String>,
    request_id: Option<u64>,
) -> anyhow::Result<Arc<Mutex<PeerConnection>>> {
    // 创建数据通道
    let ice_agent = new_ice_connection(remote_peer_id).await?;
    //设置远程
    let _ = set_remote_candidate_by_string(ice_agent.clone(), remote_candidates).await?;
    //
    let data = get_local_description_string(ice_agent.clone()).await?;

    let mut peer =
        PeerConnection::new_answer(remote_peer_id, remote_peer_id, None, ice_agent.clone());

    let peer_connection = Arc::new(Mutex::new(peer));
    //插入初始状态
    push_peer_connection(remote_peer_id, peer_connection.clone())?;

    tracing::debug!("发送{}:{}", remote_peer_id, data);
    let send_res = send_string(&serde_json::to_string(&serde_json::json!({
        "type": "relay",
        "data": {
            "type": "unicastResponse",
            "data": {
                "peer_id": remote_peer_id,
                "data": {
                    "type": "ice",
                    "data": {
                        "type": "dial_response",
                        "data": data
                    }
                }
            }
        },
        "request_id": request_id
    }))?)
    .await;
    match send_res {
        Ok(_) => {
            tracing::debug!("发送拨号响应成功!");
        }
        Err(err) => {
            tracing::error!("发送失败!{}", err);
            if let Err(err) = remove_connection(remote_peer_id) {}
            return Err(anyhow::anyhow!("发送dial_response到信令服务器失败!"));
        }
    }

    sleep(Duration::from_secs(1));

    let (done_tx, mut done_rx) = tokio::sync::mpsc::channel::<()>(1);
    tracing::debug!("等待连接......");
    //
    let conn = ice_agent
        .accept(done_rx, remote_ufrag.clone(), remote_pwd.clone())
        .await?;

    let sender = create_ice_data_channel(ice_agent.clone(), conn.clone(), remote_peer_id).await?;

    tracing::debug!("PeerConnection::new_answer......");
    //更新状态
    if let Err(err) =
        update_peer_connection(remote_peer_id, PeerConnectionState::Setuped, Some(sender))
    {}

    Ok(peer_connection)
}

async fn _create_follower_channel(
    remote_peer_id: &String,
    remote_ufrag: &String,
    remote_pwd: &String,
    remote_candidates: &Vec<String>,
) -> anyhow::Result<Arc<Mutex<PeerConnection>>> {
    let follower_connection = get_peer_connection(remote_peer_id)?;

    let ice_agent = {
        follower_connection
            .lock()
            .map_err(|err| anyhow::anyhow!("{}", err))?
            .agent
            .clone()
    };

    //设置远程
    let _ = set_remote_candidate_by_string(ice_agent.clone(), remote_candidates).await?;

    let (done_tx, mut done_rx) = tokio::sync::mpsc::channel::<()>(1);
    //
    let conn = ice_agent
        .dial(done_rx, remote_ufrag.clone(), remote_pwd.clone())
        .await?;

    let sender = create_ice_data_channel(ice_agent.clone(), conn.clone(), remote_peer_id).await?;

    //更新状态
    update_peer_connection(remote_peer_id, PeerConnectionState::Setuped, Some(sender))
}

async fn _prepare_follower_channel(
    remote_peer_id: &String,
) -> anyhow::Result<Arc<Mutex<PeerConnection>>> {
    // 创建agent
    let ice_agent = new_ice_connection(remote_peer_id).await?;

    //获取到
    let peer = PeerConnection::new_offer(remote_peer_id, remote_peer_id, ice_agent.clone());

    let data: serde_json::Value = get_local_description_string(ice_agent.clone()).await?;

    let peer_connection = Arc::new(Mutex::new(peer));
    //插入
    push_peer_connection(remote_peer_id, peer_connection.clone())?;

    let result = crate::signaling::request_response(
        &String::from("relay"),
        serde_json::json!({
            "type": "unicast",
            "data": {
                "peer_id": remote_peer_id,
                "data": {
                    "type": "ice",
                    "data": {
                        "type": "dial",
                        "data": data
                    }
                }
            }
        }),
        60000,
    )
    .await;

    match result {
        Ok(dial_response_msg) => {
            tracing::debug!("发送dial指令成功{}", remote_peer_id);
            if let Err(err) =
                update_peer_connection(remote_peer_id, PeerConnectionState::Dailed, None)
            {
            }
            //dial_response
            if let Some(err) = dial_response_msg.err {
                //
                tracing::error!("发送dial失败{}", err);
                if let Err(_) = remove_connection(remote_peer_id) {}
                return Err(anyhow::anyhow!("发送dial到信令服务器失败!{}", err));
            } else {
                let peer_id = &dial_response_msg.src;
                let request_id = dial_response_msg.request_id.clone();
                //
                match dial_response_msg.data {
                    Some(crate::signaling::SignalMessageContent::Ice { err, data }) => {
                        if let Some(err) = err {
                            tracing::error!("接收dial失败{}", err);
                            if let Err(_) = remove_connection(remote_peer_id) {}
                            return Err(anyhow::anyhow!("接收dial到信令服务器失败!{}", err));
                        } else if let Some(IceMessage::DialResponse(message)) = data {
                            //
                            if let Err(err) = dial_response(remote_peer_id, &message, request_id).await {
                                tracing::error!("dial_response处理失败{}", err);
                                if let Err(_) = remove_connection(remote_peer_id) {}
                                return Err(anyhow::anyhow!("dial_response处理失败!{}", err));
                            } else {
                                //成功
                                tracing::info!("拨号成功!");
                            }
                        } else {
                            tracing::error!("返回的消息类型不对！");
                            if let Err(err) = remove_connection(remote_peer_id) {}
                            return Err(anyhow::anyhow!("返回的消息类型不对！!"));
                        }
                    }
                    _ => {
                        tracing::error!("返回的消息类型不对！");
                        if let Err(err) = remove_connection(remote_peer_id) {}
                        return Err(anyhow::anyhow!("返回的消息类型不对！!"));
                    }
                }
            }
        }
        Err(err) => {
            tracing::error!("发送dial失败{}", err);
            if let Err(err) = remove_connection(remote_peer_id) {}
            return Err(anyhow::anyhow!("发送dial到信令服务器失败!{}", err));
        }
    }

    Ok(peer_connection)
}
